/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of JoinUs!.

JoinUs! is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

JoinUs! is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with JoinUs!. If not, see <http://www.gnu.org/licenses/>. */
package br.ufes.cwtools.joinus.services;

import java.io.StringReader;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.xml.sax.InputSource;

import br.ufes.cwtools.joinus.home.message.Message;
import br.ufes.cwtools.joinus.util.ServerCom;

import android.app.Service;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class PollingDaemon extends Service {
	private static final long INTERVAL = 10000; // Em milissegundos; intervalo de atualização do polling.
	private Timer timer;
	private Location updatedLocation = null;
	
	private static final long MIN_TIME = 60000;  // Em milissegundos.
	private static final float MIN_DISTANCE = 0;  // Em metros.

	private LocationManager manager;
	private LocationListener locationListener;
	
	@Override
	public void onCreate() {
		super.onCreate();
		timer = new Timer();
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		String username = intent.getStringExtra("username");
		String password = intent.getStringExtra("password");
		if (username != null && password != null) {
			timer.scheduleAtFixedRate(new PollingTimerTask(username, password), INTERVAL, INTERVAL);
			setupLocation();
		} else {
			Log.w("ERROR", "PollingDaemon could not get username and password from intent.");
		}
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		timer.cancel();
		//TODO: Não está resolvendo os updates duplicados...
		if (locationListener != null) manager.removeUpdates(locationListener);
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private class PollingTimerTask extends TimerTask {
		private String username;
		private SQLiteDatabase database;
		
		public PollingTimerTask(String username, String password) {
			this.username = username;
		}
		
		@Override
		public void run() {
			database = openOrCreateDatabase("homedb", MODE_PRIVATE, null);
			getMessages();
			database.close();
		}
		
		private void getMessages() {
			/* Se existir uma localização atualizada, manda ela para o servidor,
			 * senão, manda a referência nula mesmo. Como não estou checando se
			 * o updatedLocation é nulo ou não, preciso anulá-lo sempre, após
			 * fazer a chamada de sincronização. */
			String xml = ServerCom.getMsgsAndUpdatePosition(updatedLocation);
			updatedLocation = null;

			if (xml == null) {
				Log.w("ERROR", "PollingDaemon: null xml returned on getMessages().");
				return;
			}
			
			Vector<Message>v = (new Message()).fromXml(new InputSource(new StringReader(xml)));
			for(Message i : v) {
				i.insertIntoDB(database, username);
			}
		}
	}
	
	private void setupLocation() {
		manager = (LocationManager) getSystemService(LOCATION_SERVICE);

		locationListener = new LocationListener() {
			public void onStatusChanged(String provider, int status, Bundle extras) {}
			
			public void onLocationChanged(Location location) {
				updatedLocation = location;
			}

			public void onProviderDisabled(String provider) {}

			public void onProviderEnabled(String provider) {}
		};
		
		manager.requestLocationUpdates("gps", MIN_TIME, MIN_DISTANCE, locationListener);
	}
}
